<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高级网站代码提取器</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css">
    <style>
        :root {
            --primary-color: #4361ee;
            --secondary-color: #3a0ca3;
            --accent-color: #7209b7;
            --light-color: #f8f9fa;
            --dark-color: #212529;
            --success-color: #4bb543;
            --warning-color: #ffc107;
            --danger-color: #dc3545;
        }
        
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f5f7fa;
            color: var(--dark-color);
            line-height: 1.6;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }
        
        header {
            background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
            color: white;
            padding: 20px;
            text-align: center;
        }
        
        h1 {
            font-size: 2rem;
            margin-bottom: 10px;
        }
        
        .description {
            font-size: 0.9rem;
            opacity: 0.9;
            max-width: 600px;
            margin: 0 auto;
        }
        
        .control-panel {
            padding: 20px;
            background-color: var(--light-color);
            border-bottom: 1px solid #e9ecef;
        }
        
        .input-group {
            margin-bottom: 15px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: var(--dark-color);
        }
        
        input[type="url"] {
            width: 100%;
            padding: 12px 15px;
            border: 2px solid #e9ecef;
            border-radius: 6px;
            font-size: 1rem;
            transition: border-color 0.3s;
        }
        
        input[type="url"]:focus {
            border-color: var(--primary-color);
            outline: none;
            box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.2);
        }
        
        .options {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            margin-bottom: 15px;
        }
        
        .checkbox-group {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .checkbox-group input {
            width: 18px;
            height: 18px;
        }
        
        .button-group {
            display: flex;
            gap: 10px;
            margin-top: 15px;
        }
        
        button {
            padding: 12px 20px;
            border: none;
            border-radius: 6px;
            font-size: 1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .primary-btn {
            background-color: var(--primary-color);
            color: white;
        }
        
        .primary-btn:hover {
            background-color: var(--secondary-color);
            transform: translateY(-2px);
        }
        
        .secondary-btn {
            background-color: white;
            color: var(--primary-color);
            border: 2px solid var(--primary-color);
        }
        
        .secondary-btn:hover {
            background-color: rgba(67, 97, 238, 0.1);
        }
        
        .danger-btn {
            background-color: var(--danger-color);
            color: white;
        }
        
        .danger-btn:hover {
            background-color: #c82333;
        }
        
        .status {
            margin-top: 15px;
            padding: 12px;
            border-radius: 6px;
            display: none;
        }
        
        .loading {
            background-color: rgba(255, 193, 7, 0.2);
            color: var(--warning-color);
        }
        
        .error {
            background-color: rgba(220, 53, 69, 0.2);
            color: var(--danger-color);
        }
        
        .success {
            background-color: rgba(75, 181, 67, 0.2);
            color: var(--success-color);
        }
        
        .result-container {
            padding: 20px;
        }
        
        .tab-buttons {
            display: flex;
            border-bottom: 1px solid #e9ecef;
            margin-bottom: 15px;
        }
        
        .tab-btn {
            padding: 10px 20px;
            background: none;
            border: none;
            border-bottom: 3px solid transparent;
            color: var(--dark-color);
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .tab-btn.active {
            color: var(--primary-color);
            border-bottom-color: var(--primary-color);
        }
        
        .tab-content {
            display: none;
            position: relative;
        }
        
        .tab-content.active {
            display: block;
        }
        
        .code-container {
            position: relative;
            border-radius: 6px;
            overflow: hidden;
            margin-bottom: 15px;
        }
        
        .code-header {
            background-color: #343a40;
            color: white;
            padding: 8px 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .copy-btn {
            background-color: rgba(255, 255, 255, 0.2);
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 0.8rem;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        
        .copy-btn:hover {
            background-color: rgba(255, 255, 255, 0.3);
        }
        
        pre {
            margin: 0;
            padding: 0;
        }
        
        code {
            font-family: 'Courier New', Courier, monospace;
            font-size: 0.9rem;
            line-height: 1.5;
        }
        
        .hljs {
            padding: 15px;
            max-height: 500px;
            overflow-y: auto;
        }
        
        .combined-html {
            margin-top: 30px;
        }
        
        @media (max-width: 768px) {
            .container {
                border-radius: 0;
            }
            
            .button-group {
                flex-direction: column;
            }
            
            button {
                width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>高级网站代码提取器</h1>
            <p class="description">提取任何网站的HTML、CSS和JavaScript代码，并可选择合并到单个HTML文件中</p>
        </header>
        
        <div class="control-panel">
            <div class="input-group">
                <label for="url">网站URL</label>
                <input type="url" id="url" placeholder="https://example.com" required>
            </div>
            
            <div class="options">
                <div class="checkbox-group">
                    <input type="checkbox" id="extractCss" checked>
                    <label for="extractCss">提取CSS</label>
                </div>
                
                <div class="checkbox-group">
                    <input type="checkbox" id="extractJs" checked>
                    <label for="extractJs">提取JavaScript</label>
                </div>
                
                <div class="checkbox-group">
                    <input type="checkbox" id="combineFiles" checked>
                    <label for="combineFiles">合并到HTML</label>
                </div>
            </div>
            
            <div class="button-group">
                <button class="primary-btn" id="fetchBtn">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                        <path d="M8 0a8 8 0 1 0 8 8 8.009 8.009 0 0 0-8-8zm0 12a4 4 0 1 1 0-8 4 4 0 0 1 0 8z"/>
                        <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3.5a.5.5 0 0 1-.5-.5v-4A.5.5 0 0 1 8 4z"/>
                    </svg>
                    提取代码
                </button>
                
                <button class="secondary-btn" id="downloadBtn" disabled>
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                        <path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
                        <path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
                    </svg>
                    下载全部
                </button>
                
                <button class="danger-btn" id="clearBtn">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                        <path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
                        <path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
                    </svg>
                    清除
                </button>
            </div>
            
            <div id="status" class="status"></div>
        </div>
        
        <div class="result-container">
            <div class="tab-buttons">
                <button class="tab-btn active" data-tab="html">HTML</button>
                <button class="tab-btn" data-tab="css">CSS</button>
                <button class="tab-btn" data-tab="js">JavaScript</button>
                <button class="tab-btn" data-tab="combined">合并HTML</button>
            </div>
            
            <div id="html-tab" class="tab-content active">
                <div class="code-container">
                    <div class="code-header">
                        <span>HTML代码</span>
                        <button class="copy-btn" data-target="html-code">复制</button>
                    </div>
                    <pre><code id="html-code" class="language-html"></code></pre>
                </div>
            </div>
            
            <div id="css-tab" class="tab-content">
                <div class="code-container">
                    <div class="code-header">
                        <span>CSS代码</span>
                        <button class="copy-btn" data-target="css-code">复制</button>
                    </div>
                    <pre><code id="css-code" class="language-css"></code></pre>
                </div>
            </div>
            
            <div id="js-tab" class="tab-content">
                <div class="code-container">
                    <div class="code-header">
                        <span>JavaScript代码</span>
                        <button class="copy-btn" data-target="js-code">复制</button>
                    </div>
                    <pre><code id="js-code" class="language-javascript"></code></pre>
                </div>
            </div>
            
            <div id="combined-tab" class="tab-content">
                <div class="code-container">
                    <div class="code-header">
                        <span>合并后的HTML代码</span>
                        <button class="copy-btn" data-target="combined-code">复制</button>
                    </div>
                    <pre><code id="combined-code" class="language-html"></code></pre>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/css.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/javascript.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/xml.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 初始化代码高亮
            hljs.highlightAll();
            
            // 标签切换功能
            const tabBtns = document.querySelectorAll('.tab-btn');
            const tabContents = document.querySelectorAll('.tab-content');
            
            tabBtns.forEach(btn => {
                btn.addEventListener('click', function() {
                    const tabId = this.getAttribute('data-tab');
                    
                    // 移除所有active类
                    tabBtns.forEach(b => b.classList.remove('active'));
                    tabContents.forEach(c => c.classList.remove('active'));
                    
                    // 添加active类到当前标签和内容
                    this.classList.add('active');
                    document.getElementById(`${tabId}-tab`).classList.add('active');
                });
            });
            
            // 复制按钮功能
            document.querySelectorAll('.copy-btn').forEach(btn => {
                btn.addEventListener('click', function() {
                    const targetId = this.getAttribute('data-target');
                    const codeElement = document.getElementById(targetId);
                    const textToCopy = codeElement.textContent;
                    
                    navigator.clipboard.writeText(textToCopy).then(() => {
                        const originalText = this.textContent;
                        this.textContent = '已复制!';
                        setTimeout(() => {
                            this.textContent = originalText;
                        }, 2000);
                    }).catch(err => {
                        console.error('复制失败: ', err);
                    });
                });
            });
            
            // 清除按钮功能
            document.getElementById('clearBtn').addEventListener('click', function() {
                document.getElementById('url').value = '';
                document.getElementById('html-code').textContent = '';
                document.getElementById('css-code').textContent = '';
                document.getElementById('js-code').textContent = '';
                document.getElementById('combined-code').textContent = '';
                document.getElementById('status').textContent = '';
                document.getElementById('status').className = 'status';
                document.getElementById('downloadBtn').disabled = true;
                
                // 重置标签到HTML
                tabBtns.forEach(b => b.classList.remove('active'));
                tabContents.forEach(c => c.classList.remove('active'));
                document.querySelector('[data-tab="html"]').classList.add('active');
                document.getElementById('html-tab').classList.add('active');
            });
            
            // 提取代码功能
            document.getElementById('fetchBtn').addEventListener('click', function() {
                const url = document.getElementById('url').value.trim();
                const extractCss = document.getElementById('extractCss').checked;
                const extractJs = document.getElementById('extractJs').checked;
                const combineFiles = document.getElementById('combineFiles').checked;
                const statusDiv = document.getElementById('status');
                
                if (!url) {
                    showStatus('请输入有效的URL', 'error');
                    return;
                }
                
                // 验证URL格式
                try {
                    new URL(url);
                } catch (e) {
                    showStatus('请输入有效的URL（包含http://或https://）', 'error');
                    return;
                }
                
                // 显示加载状态
                showStatus('正在获取代码，请稍候...', 'loading');
                document.getElementById('downloadBtn').disabled = true;
                
                // 清空之前的代码
                document.getElementById('html-code').textContent = '';
                document.getElementById('css-code').textContent = '';
                document.getElementById('js-code').textContent = '';
                document.getElementById('combined-code').textContent = '';
                
                // 使用CORS代理获取HTML
                fetchHtml(url)
                    .then(html => {
                        document.getElementById('html-code').textContent = html;
                        hljs.highlightElement(document.getElementById('html-code'));
                        
                        // 提取CSS
                        if (extractCss) {
                            const cssUrls = extractResourceUrls(html, 'stylesheet');
                            const cssContent = extractInlineCss(html);
                            
                            if (cssUrls.length > 0 || cssContent) {
                                return Promise.all([
                                    ...cssUrls.map(fetchCss),
                                    Promise.resolve(cssContent)
                                ]).then(results => {
                                    const allCss = results.filter(Boolean).join('\n\n');
                                    document.getElementById('css-code').textContent = allCss;
                                    hljs.highlightElement(document.getElementById('css-code'));
                                    return { html, css: allCss };
                                });
                            }
                        }
                        
                        return { html, css: '' };
                    })
                    .then(({ html, css }) => {
                        // 提取JavaScript
                        if (extractJs) {
                            const jsUrls = extractResourceUrls(html, 'script');
                            const jsContent = extractInlineJs(html);
                            
                            if (jsUrls.length > 0 || jsContent) {
                                return Promise.all([
                                    ...jsUrls.map(fetchJs),
                                    Promise.resolve(jsContent)
                                ]).then(results => {
                                    const allJs = results.filter(Boolean).join('\n\n');
                                    document.getElementById('js-code').textContent = allJs;
                                    hljs.highlightElement(document.getElementById('js-code'));
                                    return { html, css, js: allJs };
                                });
                            }
                        }
                        
                        return { html, css, js: '' };
                    })
                    .then(({ html, css, js }) => {
                        // 合并到单个HTML文件
                        if (combineFiles) {
                            const combinedHtml = createCombinedHtml(html, css, js);
                            document.getElementById('combined-code').textContent = combinedHtml;
                            hljs.highlightElement(document.getElementById('combined-code'));
                        }
                        
                        showStatus('代码提取完成!', 'success');
                        document.getElementById('downloadBtn').disabled = false;
                    })
                    .catch(error => {
                        console.error('提取代码失败:', error);
                        showStatus(`提取代码失败: ${error.message}`, 'error');
                    });
            });
            
            // 下载功能
            document.getElementById('downloadBtn').addEventListener('click', function() {
                const html = document.getElementById('html-code').textContent;
                const css = document.getElementById('css-code').textContent;
                const js = document.getElementById('js-code').textContent;
                const combined = document.getElementById('combined-code').textContent;
                
                if (combined) {
                    downloadFile('combined.html', combined);
                } else if (html) {
                    downloadFile('extracted.html', html);
                }
            });
            
            // 辅助函数
            function showStatus(message, type) {
                const statusDiv = document.getElementById('status');
                statusDiv.textContent = message;
                statusDiv.className = `status ${type}`;
                statusDiv.style.display = 'block';
            }
            
            function fetchHtml(url) {
                const proxyUrl = `https://api.codetabs.com/v1/proxy/?quest=${encodeURIComponent(url)}`;
                return fetch(proxyUrl)
                    .then(response => {
                        if (!response.ok) throw new Error('获取HTML失败');
                        return response.text();
                    });
            }
            
            function fetchCss(url) {
                const proxyUrl = `https://api.codetabs.com/v1/proxy/?quest=${encodeURIComponent(url)}`;
                return fetch(proxyUrl)
                    .then(response => {
                        if (!response.ok) throw new Error(`获取CSS失败: ${url}`);
                        return response.text();
                    })
                    .then(css => `/* ${url} */\n\n${css}`);
            }
            
            function fetchJs(url) {
                const proxyUrl = `https://api.codetabs.com/v1/proxy/?quest=${encodeURIComponent(url)}`;
                return fetch(proxyUrl)
                    .then(response => {
                        if (!response.ok) throw new Error(`获取JavaScript失败: ${url}`);
                        return response.text();
                    })
                    .then(js => `/* ${url} */\n\n${js}`);
            }
            
            function extractResourceUrls(html, type) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                const urls = [];
                
                if (type === 'stylesheet') {
                    const links = doc.querySelectorAll('link[rel="stylesheet"]');
                    links.forEach(link => {
                        const href = link.getAttribute('href');
                        if (href) {
                            urls.push(new URL(href, document.getElementById('url').value).href);
                        }
                    });
                } else if (type === 'script') {
                    const scripts = doc.querySelectorAll('script[src]');
                    scripts.forEach(script => {
                        const src = script.getAttribute('src');
                        if (src) {
                            urls.push(new URL(src, document.getElementById('url').value).href);
                        }
                    });
                }
                
                return urls;
            }
            
            function extractInlineCss(html) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                const styles = doc.querySelectorAll('style');
                let inlineCss = '';
                
                styles.forEach(style => {
                    inlineCss += style.textContent + '\n\n';
                });
                
                return inlineCss.trim();
            }
            
            function extractInlineJs(html) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                const scripts = doc.querySelectorAll('script:not([src])');
                let inlineJs = '';
                
                scripts.forEach(script => {
                    inlineJs += script.textContent + '\n\n';
                });
                
                return inlineJs.trim();
            }
            
            function createCombinedHtml(html, css, js) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                
                // 移除所有外部CSS和JS引用
                doc.querySelectorAll('link[rel="stylesheet"]').forEach(link => link.remove());
                doc.querySelectorAll('script[src]').forEach(script => script.remove());
                
                // 添加内联CSS
                if (css) {
                    const style = doc.createElement('style');
                    style.textContent = css;
                    doc.head.appendChild(style);
                }
                
                // 添加内联JS
                if (js) {
                    const script = doc.createElement('script');
                    script.textContent = js;
                    doc.body.appendChild(script);
                }
                
                // 返回格式化后的HTML
                return `<!DOCTYPE html>\n${doc.documentElement.outerHTML}`;
            }
            
            function downloadFile(filename, content) {
                const blob = new Blob([content], { type: 'text/html' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = filename;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
            }
        });
    </script>
</body>
</html>